#include <bandit/bandit.h>
using namespace snowhouse;
using namespace bandit;
/** Those files will be tested **/
#include <Cal.h>
#include <Fibonacci.h>
#include <Braces.h>
#include <Factorial.h>
/** Those files will be tested **/
go_bandit([]() {
    // 简单测试自定义模板类的加减乘除以及复杂运算
    describe("test Cal<int>", []() {
        Cal<int> intcal;
        it("test01. add 2+3", [&]() { AssertThat(intcal.add(2, 3), Equals(4)); });
        it("test02. sub 2-4", [&]() { AssertThat(intcal.sub(2, 4), Equals(-2)); });
        it("test03. mul 8*9", [&]() { AssertThat(intcal.mul(8, 9), Equals(72)); });
        it("test04. div 2/4", [&]() { AssertThat(intcal.div(2, 4), Equals(0)); });
        it("test05. mutli operation 1+2*3+4",
           [&]() { AssertThat(intcal.add(intcal.add(1, intcal.mul(2, 3)), 4), Equals(11)); });
        it("test06. 1+2!=4", [&]() { AssertThat(intcal.add(1, 2), !Equals(4)); });
        it("test07. 1+2<4", [&]() { AssertThat(intcal.add(1, 2), IsLessThan(4)); });
        it("test08. 13< 7+9 <18",
           [&]() { AssertThat(intcal.add(7, 9), IsLessThan(18) && IsGreaterThan(13)); });
        it("test09. 13< 7+9 or 15< 7+9",
           [&]() { AssertThat(intcal.add(7, 9), IsGreaterThan(15) || IsGreaterThan(13)); });
    });
    // 测试bandit该框架提供的谓语判断
    describe("test boolean operators", []() {
        it("test01 IsFalse()", []() { AssertThat(false, IsFalse()); });
        it("test02 failing IsFalse()", []() { AssertThat(true, !IsFalse()); });
        it("test03 IsTrue()", []() { AssertThat(true, IsTrue()); });
        it("test04 failing IsTrue()", []() { AssertThat(false, !IsTrue()); });
        it("test05 Is().True()", []() { AssertThat(true, Is().True()); });
        it("test06 Is().False()", []() { AssertThat(false, Is().False()); });
        it("test07 false==false", []() { AssertThat(false, Equals(false)); });
        it("test08 true==true", []() { AssertThat(true, Equals(true)); });
        it("test09 (false==false) == true", []() { AssertThat(false == false, Equals(true)); });
        it("test10 (false!=false) == false", []() { AssertThat(false != false, Is().False()); });
    });
    // 测试斐波那契数列（0，1，1，2，...）的正确性与组合性
    describe("test fibonacci sequence", []() {
        Fib seq;
        it("test01 fib(0)==0", [&]() { AssertThat(seq[0], Equals(0)); });
        it("test02 fib(1)==1", [&]() { AssertThat(seq[1], Equals(1)); });
        it("test03 fib(8)==21", [&]() { AssertThat(seq[8], Equals(21)); });
        it("test04 fib(7)+fib(8)=fib(9)", [&]() { AssertThat(seq[7] + seq[8], Equals(seq[9])); });
        it("test05 fib(7)+fib(8)*2==fib(10)",
           [&]() { AssertThat(seq[7] + seq[8] * 2, Equals(seq[10])); });
        it("test06 fib(11)!=90", [&]() { AssertThat(seq[11], !Equals(90)); });
        it("test07 fib(36)==14930352", [&]() { AssertThat(seq[36], Equals(14930352)); });
        it("test08 fib(40)==102334155", [&]() { AssertThat(seq[40], Equals(102334155)); });
        it("test09 seq(13)!=seq(14)", [&]() { AssertThat(seq[13], !Equals(seq[14])); });
        it("test10 seq(1)==seq(2)", [&]() { AssertThat(seq[1], Equals(seq[2])); });
    });
    // 测试括号是否正确匹配
    describe("test vaild braces", []() {
        it("test01 (){}[]   =>  true", []() { AssertThat(valid_braces("(){}[]"), IsTrue()); });
        it("test02 ([{}])   =>  true", []() { AssertThat(valid_braces("([{}])"), IsTrue()); });
        it("test03 (}   =>  false", []() { AssertThat(valid_braces("(}"), IsFalse()); });
        it("test04 [(]) =>  false", []() { AssertThat(valid_braces("[(])"), IsFalse()); });
        it("test05 [({})](] =>  false", []() { AssertThat(valid_braces("[({})](]"), IsFalse()); });
        it("test06 [()])    =>  false", []() { AssertThat(valid_braces("[()])"), IsFalse()); });
        it("test07 []({}({{{(){}}}}))   =>  true",
           []() { AssertThat(valid_braces("[]({}({{{(){}}}}))"), IsTrue()); });
        it("test08 [({(([])]})))[]  => false",
           []() { AssertThat(valid_braces("[({(([])]})))[]"), IsFalse()); });
        it("test09 [({)]    =>  false", []() { AssertThat(valid_braces("[({)]"), IsFalse()); });
    });
    // 测试结果为大整数的阶乘算法是否正确
    describe("test large factorials", []() {
        it("test01 0!", []() { AssertThat(factorial(0), Equals("1")); });
        it("test02 1!", []() { AssertThat(factorial(1), Equals("1")); });
        it("test03 10!", []() { AssertThat(factorial(10), Equals("3628800")); });
        it("test04 15!", []() { AssertThat(factorial(15), Equals("1307674368000")); });
        it("test05 20!", []() { AssertThat(factorial(20), Equals("2432902008176640000")); });
        it("test06 40!", []() {
            AssertThat(factorial(40), Equals("815915283247897734345611269596115894272000000000"));
        });
        it("test07 60!", []() {
            AssertThat(factorial(60),
                       Equals("832098711274139014427634118322336438075417260636124595244927"
                              "7696409600000000000000"));
        });
        it("test08 80!", []() {
            AssertThat(factorial(80),
                       Equals("715694570462638022948115337231865321655846573423657525771094"
                              "45058227039255480148842668944867280814080000000000000000000"));
        });
        it("test09 100!", []() {
            AssertThat(factorial(100),
                       Equals("933262154439441526816992388562667004907159682643816214685929"
                              "638952175999932299156089414639761565182862536979208272237582"
                              "51185210916864000000000000000000000000"));
        });
    });

});
int main(int argc, char *argv[])
{
    // run all tests
    return bandit::run(argc, argv);
}
